package mqttClient

import (
	"encoding/base64"
	"errors"
	"fmt"
	"gitee.com/fierce_wolf/go-fox-edge-common/commConfig"
	"gitee.com/fierce_wolf/go-fox-edge-common/commMqtt"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/ChanSyncObj"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Hex"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Json"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Map"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Uuid"
	"gitee.com/fierce_wolf/go-fox-edge-common/edgeEnv"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"go-fox-edge-channel-mqtt-client/scriptEngine"
	"strings"
	"time"
)

type mqttClient struct {
	client *commMqtt.MqttClient
}

func (e *mqttClient) GetDefaultHandler() mqtt.MessageHandler {
	return func(client mqtt.Client, msg mqtt.Message) {
		fmt.Printf("TOPIC: %s\n", msg.Topic())
		fmt.Printf("MSG: %s\n", msg.Payload())
	}
}

func (e *mqttClient) instance() (err error) {
	defer func() {
		if e := recover(); e != nil {
			message := fmt.Sprintf("解析全局配置serverConfig 失败:%v", e)
			err = errors.New(message)
		}
	}()

	// 获得系统配置参数
	configValue, err := commConfig.GetConfigParam("serverConfig")
	if err != nil {
		return fmt.Errorf("mqtt参数初始化失败：找不到serverConfig配置项")
	}

	// 取出系统配置参数
	mqtt := Map.GetMap(configValue, "mqtt", make(map[string]interface{}))
	if mqtt == nil {
		return fmt.Errorf("mqtt参数初始化失败")
	}

	clientId := Map.GetString(mqtt, "clientId", "")
	if clientId == "" {
		clientId = Uuid.RandomUUID()
	}

	subscribes := scriptEngine.Subscribes()

	// 设置MQTT的通信参数
	client := commMqtt.NewClient(clientId, mqtt)
	e.client = client

	// 向MQTT BROKER注册订阅topic
	for _, topic := range subscribes {
		handler := &mqttHandler{}
		handler.clientId = clientId
		handler.subscribe = topic
		e.client.Subscribe(topic, handler.Handler())
	}

	// 开始连接
	go e.connect()

	return nil
}

func (e *mqttClient) connect() {
	time.Sleep(3 * time.Second)
	for e.client.Connect() != nil {
		time.Sleep(3 * time.Second)
	}
}

func (e *mqttClient) GetMqttClient() *commMqtt.MqttClient {
	return e.client
}

func (e *mqttClient) GetTopicDownlink() (string, error) {
	// 获得系统配置参数
	configValue, err := commConfig.GetConfigParam("serverConfig")
	if err != nil {
		return "", err
	}

	// 取出系统配置参数
	topics := Map.GetMap(configValue, "topic", make(map[string]interface{}))
	if topics == nil {
		return "", errors.New("配置参数缺失：topic")
	}

	downlink := Map.GetString(topics, "downlink", "")
	if downlink == "" {
		return "", errors.New("配置参数缺失：topic下缺失downlink")
	}
	downlink = strings.ReplaceAll(downlink, "{gatewayEui}", edgeEnv.GetCPUID())

	return downlink, nil
}

func (e *mqttClient) Request(devEUI string, fport int, request string, timeout int) (interface{}, error) {
	// 取出mqtt的client，用来发送数据
	if e.client == nil || !e.client.IsConnected() {
		return nil, errors.New("mqtt客户端，尚未与mqtt broker建立链接：")
	}

	// 从全局配置中，取出下行的topic
	topic, err := e.GetTopicDownlink()
	if err != nil {
		return nil, err
	}
	topic = strings.ReplaceAll(topic, "$deveui", devEUI)

	// HEX数据转换成PDU
	pdu := Hex.DecodeString(request)
	if len(pdu) == 0 {
		return nil, errors.New("发送数据的格式不正确：" + request)
	}

	// body的数据
	body := make(map[string]interface{})
	body["devEUI"] = devEUI
	body["confirmed"] = true
	body["fport"] = fport
	body["data"] = base64.StdEncoding.EncodeToString(Hex.DecodeString(request))
	json := Json.BuildJson(body)

	// 推送数据给mqtt broker
	if !e.client.Publish(topic, json, 5*000) {
		return nil, errors.New("推送数据到mqtt broker失败")
	}

	// 等到lora子设备的数据，通过lora网关，推送到mqtt broker
	recv := ChanSyncObj.Wait(devEUI, int64(timeout+1*000))
	if recv == nil {
		return nil, errors.New("没有接收到设备的数据")
	}

	return recv, nil
}
